<?php

namespace Payment\Controller;

use Util\StringUtils;
use Payment\Client\Charge;
use Payment\Config;
use Common\Controller\ApiController;
use Common\Model\ModelException;
use Util\ModelUtils;
use JiaLeo\Payment\Unionpay\AppPay;

class PaymentController extends ApiController {

    /**
     * 金榜书城
     */
    public function charge() {
        $moneyrate = C('moneyrate'); //充值额度
        $user = $this->user;
        if ($user['vip'] == 0) {
            $this->errorResponse('100001', '请先登入哦', '400');
        }
        $params = $this->request();
        $channel = filter($params['channel'], 'wx_pub');
        $id = isset($params['rate_id']) ? $params['rate_id'] : 1;
        if (empty($id) || $id > 6) {
            $this->errorResponse('10001', '选择的金额不对，请重试', 400);
        }
        if ($id < 5) {
            $type = "充值{$moneyrate[$id - 1]}书币";
            $mark = 'charge';
        } elseif ($id == 5) {
            $type = "充值季度会员";
            $mark = 'vip';
        } else {
            $type = "充值年度会员";
            $mark = 'year_vip';
        }
        $amount = $moneyrate[$id - 1];
        $orderNo = 'PAY' . StringUtils::randString(8, 1) . date('md');

        /* 写入充值记录 */
        $paymentData = [
            'uid' => $user['id'],
            'moneyall' => $amount,
            'onum' => $orderNo,
            'channel' => $channel,
            'type' => $type,
            'mark' => $mark,
            'time' => time(),
            'time2' => date("Y-m-d"),
        ];

        $chanrgeModel = D('Chanrge');
        if ($chanrgeModel->create($paymentData)) {
            $pubData = [
                'body' => $type,
                'subject' => $type,
                'order_no' => $orderNo,
                'timeout_express' => time() + 600, // 表示必须 600s 内付款
                'amount' => $amount, // 单位为元 ,最小为0.01
                'return_param' => '',
                'client_ip' => get_client_ip(),
                'goods_type' => '1', // 0 虚拟 1 实体
                'store_id' => '',
                'qr_mod' => '',
            ];
            try {

                if ($channel == 'wx_pub') {//微信支付，h5支付方式，需传openid,目前是直接获取数据库openid,对于没有用过微信登入的用户将会失效
                    $connect = D('Connect')->where(['type' => 'weixin', 'uid' => $user['id']])->find();
                    if ($connect) {
                        $pubData['openid'] = $connect['open_id'];
                    } else {
                        $this->errorResponse(30021);
                    }
                } elseif ($channel == 'wx_qr') {
                    $payData['product_id'] = 1;
                }

                $ret = $this->_unifiedorder($channel, $pubData);
                if ($ret) {
                    $chanrgeModel->add();
                }
                $this->response($ret);
            } catch (PayException $e) {
                $this->errResponse(40001, $e->getMessage(), 400);
            }
        } else {
            $this->errResponse(40002, '充值记录失败', 400);
        }
    }

    /*
     * 聊吧项目
     */

    public function charge2() {
        $user = $this->user;
        $params = $this->request();
        $channel = filter($params['channel'], 'wx_pub');
        $remark = filter($params['remark'], '零钱充值');
        $amount = $params['amount'] * 100;
        $orderNo = 'PAY' . StringUtils::randString(8, 1) . date('md');
        $type = '平台充值';
        /* 写入充值记录 */
        $paymentData = [
            'uid' => $user['id'],
            'amount' => $amount, //金额都是乘以100
            'payment_no' => $orderNo,
            'channel' => $channel,
            'type' => 'charge',
            'remark' => $remark,
            'create_time' => time(),
        ];

        $chanrgeModel = D('PaymentLog');
        if ($chanrgeModel->create($paymentData)) {
            $pubData = [
                'body' => $type,
                'subject' => $type,
                'order_no' => $orderNo,
                'timeout_express' => time() + 600, // 表示必须 600s 内付款
                'amount' => $amount, // 单位为元 ,最小为0.01
                'return_param' => '',
                'client_ip' => get_client_ip(),
                'goods_type' => '1', // 0 虚拟 1 实体
                'store_id' => '',
                'qr_mod' => '',
            ];
            try {

                if ($channel == 'wx_pub') {//微信支付，h5支付方式，需传openid,目前是直接获取数据库openid,对于没有用过微信登入的用户将会失效
                    $connect = D('Connect')->where(['type' => 'weixin', 'uid' => $user['id']])->find();
                    if ($connect) {
                        $pubData['openid'] = $connect['open_id'];
                    } else {
                        $this->errorResponse(30021);
                    }
                } elseif ($channel == 'wx_qr') {
                    $payData['product_id'] = 1;
                }

                $ret = $this->_unifiedorder($channel, $pubData);
                if ($ret) {
                    $chanrgeModel->add();
                }
                $this->response($ret);
            } catch (PayException $e) {
                $this->errResponse(40001, $e->getMessage(), 400);
            }
        } else {
            $this->errResponse(40002, '充值记录失败', 400);
        }
    }

    /**
     * 发起统一支付
     *
     * @param string $channel
     * @param array $pubData 所有支付类型的公用参数
     * @return void
     */
    private function _unifiedorder($channel, $pubData) {
        switch ($channel) {
            case 'ali_web':
            case 'ali_wap':
                $config = C('sdk.alipay');
                $payData = [
                    'body' => $pubData['body'],
                    'subject' => $pubData['subject'],
                    'order_no' => $pubData['order_no'],
                    'timeout_express' => $pubData['timeout_express'], // 表示必须 600s 内付款
                    'amount' => $pubData['amount'], // 单位为元 ,最小为0.01
                    'return_param' => $pubData['return_param'],
                    'client_ip' => $pubData['client_ip'],
                    'goods_type' => '1',
                    'store_id' => '',
                    // 说明地址：https://doc.open.alipay.com/doc2/detail.htm?treeId=270&articleId=105901&docType=1
                    // 建议什么也不填
                    'qr_mod' => '',
                ];

                try {
                    $redirectUrl = Charge::run($channel, $config, $payData);
                    return ['redirect' => $redirectUrl];
                } catch (PayException $e) {
                    throw $e;
                }
            case 'ali_app':
                $config = C('sdk.alipay');
                $payData = [
                    'body' => $pubData['body'],
                    'subject' => $pubData['subject'],
                    'order_no' => $pubData['order_no'],
                    'timeout_express' => $pubData['timeout_express'], // 表示必须 600s 内付款
                    'amount' => $pubData['amount'], // 单位为元 ,最小为0.01
                    'return_param' => $pubData['return_param'],
                    'client_ip' => $pubData['client_ip'],
                    'goods_type' => 0, // 0 虚拟 1 实体
                        // 'product_id' => $pubData['product_id'],
                        // 'openid' => $pubData['openid'],
                ];
                $ret = Charge::run($channel, $config, $payData);
                return ['param_str' => $ret, 'channel' => 'alipay'];
                break;
            case 'wx_pub':
                $config = C('sdk.wxpay');
                $payData = [
                    'body' => $pubData['body'],
                    'subject' => $pubData['subject'],
                    'order_no' => $pubData['order_no'],
                    'timeout_express' => $pubData['timeout_express'], // 表示必须 600s 内付款
                    'amount' => $pubData['amount'], // 单位为元 ,最小为0.01
                    'return_param' => $pubData['return_param'],
                    'client_ip' => $pubData['client_ip'],
                    // 'product_id' => $pubData['product_id'],
                    'openid' => $pubData['openid'],
                ];
                try {
                    $ret = Charge::run($channel, $config, $payData);
                    return ['payment' => $ret, 'channel' => 'wxpay'];
                } catch (PayException $e) {
                    throw $e;
                }
            case 'wx_app':
                $config = C('sdk.wxpay');
                $payData = [
                    'body' => $pubData['body'],
                    'subject' => $pubData['subject'],
                    'order_no' => $pubData['order_no'],
                    'timeout_express' => $pubData['timeout_express'], // 表示必须 600s 内付款
                    'amount' => $pubData['amount'], // 单位为元 ,最小为0.01
                    'return_param' => $pubData['return_param'],
                    'client_ip' => $pubData['client_ip'],
                        // 'product_id' => $pubData['product_id'],
                        // 'openid' => $pubData['openid'],
                ];
                try {
                    $ret = Charge::run($channel, $config, $payData);
                    $ret['packages'] = $ret['package'];
                    return ['param_obj' => $ret, 'channel' => 'wxpay'];
                } catch (PayException $e) {
                    throw $e;
                }
                break;
            case 'wx_wap':
                $config = C('sdk.wxpay');
                $payData = [
                    'body' => $pubData['body'],
                    'subject' => $pubData['subject'],
                    'order_no' => $pubData['order_no'],
                    'timeout_express' => $pubData['timeout_express'], // 表示必须 600s 内付款
                    'amount' => $pubData['amount'], // 单位为元 ,最小为0.01
                    'return_param' => $pubData['return_param'],
                    'client_ip' => $pubData['client_ip'],
                        // 'product_id' => $pubData['product_id'],
                        // 'openid' => $pubData['openid'],
                ];
                try {
                    $ret = Charge::run($channel, $config, $payData);
                    $ret['packages'] = $ret['package'];
                    return ['param_obj' => $ret, 'channel' => 'wxpay'];
                } catch (PayException $e) {
                    throw $e;
                }
                break;
            case 'wx_qr':
                $config = C('sdk.wxpay');
                $payData = [
                    'body' => $pubData['body'],
                    'subject' => $pubData['subject'],
                    'order_no' => $pubData['order_no'],
                    'timeout_express' => $pubData['timeout_express'], // 表示必须 600s 内付款
                    'amount' => $pubData['amount'], // 单位为元 ,最小为0.01
                    'return_param' => $pubData['return_param'],
                    'client_ip' => $pubData['client_ip'],
                    'product_id' => $pubData['product_id'],
                ];
                try {
                    $codeUrl = Charge::run($channel, $config, $payData);
                    return ['code_url' => $codeUrl, 'order_no' => $pubData['order_no']];
                } catch (PayException $e) {
                    throw $e;
                }
            case 'union_app':
                $config = C('sdk.unionpay');
                new \JiaLeo\Payment\Unionpay\BaseUnionpay($config);
                try {
                    $unionpay = new AppPay($config);
                    $payData = [
//                    'body' => $pubData['body'],
//                    'subject' => $pubData['subject'],
                        'orderId' => $pubData['order_no'],
//                    'timeout_express' => $pubData['timeout_express'], // 表示必须 600s 内付款
                        'txnAmt' => $pubData['amount'], // 单位为元 ,最小为0.01
                        'backUrl' => $config['notify_url'],
//                    'return_param' => $pubData['return_param'],
//                    'client_ip' => $pubData['client_ip'],
//                    'product_id' => $pubData['product_id'],
                    ];
                    $ret = $unionpay->handle($payData);
                    return ['param_obj' => $ret, 'channel' => 'unionpay'];
                } catch (PayException $e) {

                    throw $e;
                }
            default:
                break;
        }
    }

    public function getByOrderNo() {
        $user = $this->currentUser;
        $orderNo = I('get.order_no');
        $condition = [];
        $condition['order_no'] = $orderNo;
        $condition['uid'] = $user['id'];

        $payment = D('PaymentLog')
                ->scope('common')
                ->where($condition)
                ->find();

        $this->response($payment);
    }

    public function index() {
        $params = [];

        $startTime = I('get.start_time');
        $endTime = I('get.end_time');
        $orderNo = I('get.order_no');
        $page = I('get.page', 1);
        $perPage = I('get.per_page', 10);

        $user = $this->currentUser;

        $condition = [];
        $condition['uid'] = $user['id'];

        if ($startTime && $endTime) {
            $condition['create_time'] = ['between', [$startTime, $endTime]];
        } elseif ($startTime && empty($endTime)) {
            $condition['create_time'] = ['egt', $startTime];
        } elseif (empty($startTime) && $endTime) {
            $condition['create_time'] = ['lgt', $endTime];
        }

        if ($orderNo) {
            if (strpos($orderNo, ',') != -1) {
                $orderNo = explode(',', $orderNo);
                $condition['order_no'] = ['in', $orderNo];
            } else {
                $condition['order_no'] = $orderNo;
            }
        }

        $count = D('PaymentLog')
                ->scope('common')
                ->scope('success')
                ->where($condition)
                ->count();

        $restPage = new Page($count, $perPage);
        $restPage->addToHeader();

        $PaymentLogs = D('PaymentLog')
                ->scope('common')
                ->scope('success')
                ->where($condition)
                ->order('create_time desc')
                ->page($page, $perPage)
                ->select();
        $this->response($PaymentLogs);
    }

    /*
     * 发红包功能
     * 
     */

    public function luckmoney() {
        $input = $this->request();
        $this->checkNull($input, ['money']);
        $userinfo = $this->userinfo;
        if ($userinfo['money'] < $input['money'] * 100) {
            $this->errorResponse(10002,"余额不足");
        }
        $uid = $this->user['id'];
        try {
            $id = D('Payment')->setLuckMoney($uid, $input);
            if ($id) {
                $this->response(['id' => $id]);
            }
            $this->errorResponse('400', '创建失败');
        } catch (ModelException $e) {
            $this->errorModelResponse($e);
        }
    }

    /*
     * 获取红包详情
     */

    public function getluckmoneyinfo() {
        $input = $this->request();
        $id = $input['id'];
        $Luckmoney = D('Luckmoney')->find($id);
        if (!empty($Luckmoney)) {
            ModelUtils::hasMany($Luckmoney, ['foreignKey' => 'luckmoney_id', 'relation' => 'LuckmoneyLog', 'order' => 'create_time desc', 'refKey' => 'luckmoney_id', 'name' => 'luckmoneylog']);
            if ($Luckmoney['status'] == 2) {
                $Luckmoney['ranking'] = explode('|', $Luckmoney['ranking']);
                $max = max($Luckmoney['ranking']);
                foreach ($Luckmoney['luckmoneylog'] as $k => &$v) {
                    if ($v['luck_money'] == $max) {
                        $v['rank'] = 1;
                    }
                }
            }
            ModelUtils::belongsTo($Luckmoney, ['foreignKey' => 'user_id', 'relation' => 'Users', 'refKey' => 'user_id', 'name' => 'user']);
            ModelUtils::belongsTo($Luckmoney['luckmoneylog'], ['foreignKey' => 'luck_people', 'relation' => 'Users', 'refKey' => 'user_id', 'name' => 'user']);
        }

        $Luckmoney = transform('Payment', 'listview', $Luckmoney);
        $this->response($Luckmoney);
    }

    /*
     * 抢红包
     */

    public function getLuckmoney() {
        $input = $this->request();
        $this->checkNull($input, ['id']);
        $id = $input['id'];
        $uid = $this->user['id'];
        $res = D('Payment')->getLuckmoney($uid, $id);
        if ($res) {
            $this->createdResponse($res);
        }
        $this->errorResponse('10002', '领取失败');
    }

    /*
     * 获取某人所有未领取过红包
     */

    public function getLluckmoneyLog() {
        $input = $this->request();
        $page = filter($input['page'], 1);
        $perPage = filter($input['per_page'], 50);
        $uid = $this->user['id'];
        $LuckmoneyM = D('Luckmoney');
        $str = "%{$uid}%";
        $where['whose|user_id'] = ['like', $str];
        $count = $LuckmoneyM->where($where)->count(); //查询所有红包记录
        if ($count > 0) {
            $luckmoney = $LuckmoneyM
                    ->where($where)
                    ->order('create_time desc')
                    ->page($page, $perPage)
                    ->select();
        }
        if (!empty($luckmoney)) {//去掉已经领取过的红包
            $luckmoney_id = array_column($luckmoney, 'luckmoney_id');
            $LuckmoneyLog = D('LuckmoneyLog')->where(['luck_people' => $uid, 'luckmoney_id' => ['in', $luckmoney_id]])->order('create_time desc')->select();
            if (!empty($LuckmoneyLog)) {
                $luckmoney_ids = array_column($LuckmoneyLog, 'luckmoney_id');
                foreach ($luckmoney as $key => $value) {
                    if (in_array($value['luckmoney_id'], $luckmoney_ids)) {
                        unset($luckmoney[$key]);
                    }
                }
            }
        }
        $luckmoney = array_values($luckmoney);
        $pagination = pagination($count, $perPage, $page);
        $this->response($luckmoney, $pagination);
    }

}
